package com.iflytek.cosmo.ocr.support.license;

import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.iflytek.cosmo.ocr.common.enums.LicenseEnum;

/**
 * @author <a href=mailto:ktyi@iflytek.com>伊开堂</a>
 * @date 2021/7/1
 */
public class LicenseRunner {

    public static final Pattern VERION_PATTERN = Pattern.compile("-[v|V](\\d+)");
    public static final Pattern SIZE_PATTERN = Pattern.compile("-size=(\\d+)");
    public static final Pattern DURATION_PATTERN = Pattern.compile("-duration=(\\d+)");

    /* java -jar view-license-generator-1.0-SNAPSHOT.jar -client -v1 -size=10 -type=formal -duration=3650 */
    /* java -jar view-license-generator-1.0-SNAPSHOT.jar -server -v1 -mac=e0:00:84:2b:5d:49/e0:00:84:2b:5d:49 */
    /* java -jar view-license-generator-1.0-SNAPSHOT.jar -server -v2 -machine=036aad1b88ec4e80906d5d27ed9cef1d */
    public static void main(String[] args) throws Exception {
        if (args == null || args.length == 0) {
            System.out.println("客户端授权示例:   java -jar view-license-generator-1.0.jar -client -v1 -size=10 " +
                    "-type=formal -duration=3650 ");
            System.out.println("服务端授权示例1:   java -jar view-license-generator-1.0.jar -server -v1 " +
                    "-mac=e0:00:84:2b:5d:49/e0:00:84:2b:5d:49");
            System.out.println("服务端授权示例2:   java -jar view-license-generator-1.0.jar -server -v2 " +
                    "-machine=036aad1b88ec4e80906d5d27ed9cef1d");
        }

        for (String arg : args) {
            if (arg.equalsIgnoreCase("-client")) {
                generateClient(args);
                break;
            }
            else if (arg.equalsIgnoreCase("-server")) {
                generateServer(args);
                break;
            }
            else {
                System.out.println("授权生成失败, 未指定授权类型为客户端(-client), 还是服务端(-server)!!!");
                System.exit(-1);
            }
        }
    }

    /** 生成服务器授权信息, 并写入文件 */
    private static void generateServer(String[] args) throws Exception {
        int version = extractVersion(args);
        LicenseVersion licenseVersion = LicenseVersion.parseFromCode(version);
        if (licenseVersion == null) {
            throw new RuntimeException("授权生成失败, 暂不支持该版本: " + version + " 的服务器授权");
        }

        String license = null;
        switch (licenseVersion) {
            case V1:
                try {
                    List<String> macList = extractMacListParam(args);
                    license = LicenseMaker.generateServlerLicenseV1(macList);
                }
                catch (Exception e) {
                    System.out.println("授权生成失败, 系统异常!!!");
                    throw e;
                }
                break;
            case V2:
                try {
                    String machinedId = extractMachineIdParam(args);
                    license = LicenseMaker.generateServlerLicenseV2(machinedId);
                }
                catch (Exception e) {
                    System.out.println("授权生成失败, 系统异常!!!");
                    throw e;
                }
                break;
            default:
                throw new RuntimeException("授权生成失败, 暂不支持该版本: " + version + " 的服务器授权");
        }

        String fileName = "serverAuth_" + DateUtil.format(new Date(), "yyyyMMddHHmmss") + ".txt";
        write2File(license, fileName);
    }

    private static String extractMachineIdParam(String[] args) {
        for (String arg : args) {
            if (arg.startsWith("-machine=")) {
                String machineId = arg.substring(9);
                if (StrUtil.isNotBlank(machineId)) {
                    return machineId;
                }
            }
        }
        throw new RuntimeException("请指定机器标识, 例: -machine=036aad1b88ec4e80906d5d27ed9cef1d");
    }

    /** 授权信息写入文件 */
    private static void write2File(String license, String fileName) throws IOException {
        try (FileWriter writer = new FileWriter(fileName)) {
            writer.write(license);
        }
        catch (Exception e) {
            System.out.println("授权信息写入文件: " + fileName + "异常");
            throw e;
        }
    }

    /** 提取mac地址参数 */
    private static List<String> extractMacListParam(String[] args) {
        List<String> macList = null;
        for (String arg : args) {
            if (arg.startsWith("-mac=")) {
                String macStr = arg.substring(5);
                if (macStr != null && macStr.trim().length() > 0) {
                    String[] macArray = macStr.split("/");
                    macList = Arrays.stream(macArray).filter(Objects::nonNull).filter(s -> s.trim().length() > 0)
                                    .collect(Collectors.toList());
                }
            }
        }
        if (macList == null || macList.isEmpty()) {
            throw new RuntimeException("请指定MAC列表, 例: -mac=e0:00:84:2b:5d:49/e0:00:84:2b:5d:49 或 -mac=00-26-B9-9B-61-BF");
        }
        return macList;
    }

    /** 提取授权版本号参数 */
    private static int extractVersion(String[] args) {
        for (String arg : args) {
            Matcher matcher = VERION_PATTERN.matcher(arg);
            if (matcher.find()) {
                String versionStr = matcher.group(1);
                return Integer.parseInt(versionStr);
            }
        }
        throw new RuntimeException("请指定确定授权版本号, 例: -v1");
    }

    private static void generateClient(String[] args) throws Exception {
        int version = extractVersion(args);
        LicenseVersion licenseVersion = LicenseVersion.parseFromCode(version);
        if (licenseVersion == null) {
            throw new RuntimeException("授权生成失败, 暂不支持该版本: " + version + " 的客户端授权");
        }

        String license = null;
        String fileName = null;
        switch (licenseVersion) {
            case V1:
                int size = extractSize(args);
                LicenseEnum type = extractClientLicenseEnum(args);
                int duration = extractDuration(args);
                List<String> licenseList = LicenseMaker.generateClientLicenseV1(size, type, "P" + duration + "D");
                license = String.join("\n\n", licenseList);
                fileName = "client_license_v" + version + "_" + type.name() + "_" + DateUtil.format(new Date(),
                        "yyyyMMddHHmmss") + ".txt";
                break;
            default:

                throw new RuntimeException("授权生成失败, 暂不支持该版本: " + version + " 的客户端授权");
        }

        write2File(license, fileName);
    }

    /** 提取有效期天数 */
    private static int extractDuration(String[] args) {
        for (String arg : args) {
            Matcher matcher = DURATION_PATTERN.matcher(arg);
            if (matcher.find()) {
                String dayStr = matcher.group(1);
                return Integer.parseInt(dayStr);
            }
        }
        throw new RuntimeException("请指定有效期(天), 例: -duration=365");
    }

    /** 提取客户端授权类型 */
    private static LicenseEnum extractClientLicenseEnum(String[] args) {
        for (String arg : args) {
            if (arg.startsWith("-type=")) {
                String typeStr = arg.substring(6);
                if (typeStr != null) {
                    LicenseEnum licenseEnum = LicenseEnum.getByCode(typeStr.toLowerCase());
                    if (licenseEnum == null) {
                        throw new RuntimeException("请指定客户端授权类型(试用:trial, 正式:formal, 免授权:free), 例: -type=formal");
                    }
                    return licenseEnum;
                }
            }
        }
        throw new RuntimeException("请指定客户端授权类型(试用:trial, 正式:formal, 免授权:free), 例: -type=formal");
    }

    /** 提取授权数量 */
    private static int extractSize(String[] args) {
        for (String arg : args) {
            Matcher matcher = SIZE_PATTERN.matcher(arg);
            if (matcher.find()) {
                String sizeStr = matcher.group(1);
                return Integer.parseInt(sizeStr);
            }
        }
        throw new RuntimeException("请指定授权数量, 例: -size=365");
    }

}
